import { VantComponent } from "../common/component";
import { isImageFile, chooseFile, isVideoFile } from "./utils";
import { imageProps, videoProps, mediaProps, messageFileProps } from "./shared";
import { isBoolean, isPromise } from "../common/validator";
VantComponent({
	props: Object.assign(
		Object.assign(
			Object.assign(
				Object.assign(
					{
						disabled: Boolean,
						multiple: Boolean,
						uploadText: String,
						useBeforeRead: Boolean,
						afterRead: null,
						beforeRead: null,
						previewSize: {
							type: null,
							value: 80
						},
						name: {
							type: null,
							value: ""
						},
						accept: {
							type: String,
							value: "image"
						},
						fileList: {
							type: Array,
							value: [],
							observer: "formatFileList"
						},
						maxSize: {
							type: Number,
							value: Number.MAX_VALUE
						},
						maxCount: {
							type: Number,
							value: 100
						},
						deletable: {
							type: Boolean,
							value: true
						},
						showUpload: {
							type: Boolean,
							value: true
						},
						previewImage: {
							type: Boolean,
							value: true
						},
						previewFullImage: {
							type: Boolean,
							value: true
						},
						videoFit: {
							type: String,
							value: "contain"
						},
						imageFit: {
							type: String,
							value: "scaleToFill"
						},
						uploadIcon: {
							type: String,
							value: "photograph"
						}
					},
					imageProps
				),
				videoProps
			),
			mediaProps
		),
		messageFileProps
	),
	data: {
		lists: [],
		isInCount: true
	},
	methods: {
		formatFileList() {
			const { fileList = [], maxCount } = this.data;
			const lists = fileList.map(item =>
				Object.assign(Object.assign({}, item), {
					isImage: isImageFile(item),
					isVideo: isVideoFile(item),
					deletable: isBoolean(item.deletable) ? item.deletable : true
				})
			);
			this.setData({ lists, isInCount: lists.length < maxCount });
		},
		getDetail(index) {
			return {
				name: this.data.name,
				index: index == null ? this.data.fileList.length : index
			};
		},
		startUpload() {
			const { maxCount, multiple, lists, disabled } = this.data;
			if (disabled) return;
			chooseFile(Object.assign(Object.assign({}, this.data), { maxCount: maxCount - lists.length }))
				.then(res => {
					this.onBeforeRead(multiple ? res : res[0]);
				})
				.catch(error => {
					this.$emit("error", error);
				});
		},
		onBeforeRead(file) {
			const { beforeRead, useBeforeRead } = this.data;
			let res = true;
			if (typeof beforeRead === "function") {
				res = beforeRead(file, this.getDetail());
			}
			if (useBeforeRead) {
				res = new Promise((resolve, reject) => {
					this.$emit(
						"before-read",
						Object.assign(Object.assign({ file }, this.getDetail()), {
							callback: ok => {
								ok ? resolve() : reject();
							}
						})
					);
				});
			}
			if (!res) {
				return;
			}
			if (isPromise(res)) {
				res.then(data => this.onAfterRead(data || file));
			} else {
				this.onAfterRead(file);
			}
		},
		onAfterRead(file) {
			const { maxSize, afterRead } = this.data;
			const oversize = Array.isArray(file) ? file.some(item => item.size > maxSize) : file.size > maxSize;
			if (oversize) {
				this.$emit("oversize", Object.assign({ file }, this.getDetail()));
				return;
			}
			if (typeof afterRead === "function") {
				afterRead(file, this.getDetail());
			}
			this.$emit("after-read", Object.assign({ file }, this.getDetail()));
		},
		deleteItem(event) {
			const { index } = event.currentTarget.dataset;
			this.$emit(
				"delete",
				Object.assign(Object.assign({}, this.getDetail(index)), { file: this.data.fileList[index] })
			);
		},
		onPreviewImage(event) {
			if (!this.data.previewFullImage) return;
			const { index } = event.currentTarget.dataset;
			const { lists, showmenu } = this.data;
			const item = lists[index];
			wx.previewImage({
				urls: lists.filter(item => isImageFile(item)).map(item => item.url),
				current: item.url,
				showmenu,
				fail() {
					wx.showToast({ title: "预览图片失败", icon: "none" });
				}
			});
		},
		onPreviewVideo(event) {
			if (!this.data.previewFullImage) return;
			const { index } = event.currentTarget.dataset;
			const { lists } = this.data;
			const sources = [];
			const current = lists.reduce((sum, cur, curIndex) => {
				if (!isVideoFile(cur)) {
					return sum;
				}
				sources.push(Object.assign(Object.assign({}, cur), { type: "video" }));
				if (curIndex < index) {
					sum++;
				}
				return sum;
			}, 0);
			wx.previewMedia({
				sources,
				current,
				fail() {
					wx.showToast({ title: "预览视频失败", icon: "none" });
				}
			});
		},
		onPreviewFile(event) {
			const { index } = event.currentTarget.dataset;
			wx.openDocument({
				filePath: this.data.lists[index].url,
				showMenu: true
			});
		},
		onClickPreview(event) {
			const { index } = event.currentTarget.dataset;
			const item = this.data.lists[index];
			this.$emit("click-preview", Object.assign(Object.assign({}, item), this.getDetail(index)));
		}
	}
});
